package cn.mumzone.pos.ui.widgets;

import android.content.Context;
import android.content.res.TypedArray;
import android.graphics.Color;
import android.text.TextUtils;
import android.util.AttributeSet;
import android.util.TypedValue;
import android.view.Gravity;
import android.view.View;
import android.view.ViewGroup;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.RadioButton;
import android.widget.RadioGroup;
import android.widget.RelativeLayout;

import java.util.ArrayList;
import java.util.List;

import cn.mumzone.basic.util.ListUtil;
import cn.mumzone.pos.R;
import cn.mumzone.pos.model.LevelListEntity;
import cn.mumzone.pos.ui.widgets.tablayout.buildins.UIUtil;

/**
 * Created by JoeLjt on 2019/7/10.
 * Email: lijiateng1219@gmail.com
 * Description:
 * <p>
 * 流式布局，可传入带实体的列表，也可以只传入 String 数组
 */
public class FlowLayout<T extends FlowLayout.FlowLayoutEntity> extends RelativeLayout {

    private Context mContext;

    // 水平间距，单位为dp
    private int horizontalSpacing = dp2px(15);
    // 垂直间距，单位为dp
    private int verticalSpacing = dp2px(15);
    // 行的集合
    private List<Line> lines = new ArrayList<Line>();
    // 当前的行
    private Line line;
    // 当前行使用的空间
    private int lineSize = 0;
    // 关键字大小，单位为sp
    private int textSize = sp2px(14);
    // 关键字颜色
    private int textColorResource = R.color.selector_color_white_title;
    // 关键字背景
    private int backgroundResource = R.drawable.selector_bg_radio_button_2dp;
    // 关键字水平padding，单位为dp
    private int textPaddingH = dp2px(15);
    // 关键字垂直padding，单位为dp
    private int textPaddingV = dp2px(6);

    private OnItemClickListener mOnItemClickListener;
    private boolean isDataUpdated;
    private String mDefaultCheckStr;

    /**
     * 存储实体列表
     */
    private List<T> mDataList = new ArrayList<>();

    private RadioButton mPreButton;
    private RadioButton mCurrButton;

    public FlowLayout(Context context) {
        this(context, null);
    }

    public FlowLayout(Context context, AttributeSet attrs) {
        this(context, attrs, 0);
    }

    public FlowLayout(Context context, AttributeSet attrs, int defStyleAttr) {
        super(context, attrs, defStyleAttr);
        mContext = context;
        TypedArray typedArray = context.getTheme().obtainStyledAttributes(
                attrs, R.styleable.FlowLayoutAttrs, defStyleAttr, 0);

        int count = typedArray.getIndexCount();
        for (int i = 0; i < count; i++) {
            int attr = typedArray.getIndex(i);
            if (attr == R.styleable.FlowLayoutAttrs_horizontalSpacing) {
                horizontalSpacing = typedArray.getDimensionPixelSize(attr, dp2px(10));

            } else if (attr == R.styleable.FlowLayoutAttrs_verticalSpacing) {
                verticalSpacing = typedArray.getDimensionPixelSize(attr, dp2px(10));

            } else if (attr == R.styleable.FlowLayoutAttrs_itemSize) {
                textSize = typedArray.getDimensionPixelSize(attr, sp2px(15));

            } else if (attr == R.styleable.FlowLayoutAttrs_itemColor) {
                textColorResource = typedArray.getResourceId(attr, R.color.selector_color_white_title);

            } else if (attr == R.styleable.FlowLayoutAttrs_backgroundResource) {
                backgroundResource = typedArray.getResourceId(attr, R.drawable.selector_bg_radio_button_2dp);

            } else if (attr == R.styleable.FlowLayoutAttrs_textPaddingH) {
                textPaddingH = typedArray.getDimensionPixelSize(attr, dp2px(7));

            } else if (attr == R.styleable.FlowLayoutAttrs_textPaddingV) {
                textPaddingV = typedArray.getDimensionPixelSize(attr, dp2px(4));
            }
        }
        typedArray.recycle();
    }

    @Override
    protected void onMeasure(int widthMeasureSpec, int heightMeasureSpec) {
        super.onMeasure(widthMeasureSpec, heightMeasureSpec);

        // 实际可以用的宽和高
        int width = MeasureSpec.getSize(widthMeasureSpec) - getPaddingLeft() - getPaddingRight();
        int height = MeasureSpec.getSize(heightMeasureSpec) - getPaddingBottom() - getPaddingTop();
        int widthMode = MeasureSpec.getMode(widthMeasureSpec);
        int heightMode = MeasureSpec.getMode(heightMeasureSpec);

        // Line初始化
        restoreLine();

        for (int i = 0; i < getChildCount(); i++) {
            View child = getChildAt(i);
            // 测量所有的childView
            int childWidthMeasureSpec = MeasureSpec.makeMeasureSpec(width,
                    widthMode == MeasureSpec.EXACTLY ? MeasureSpec.AT_MOST : widthMode);
            int childHeightMeasureSpec = MeasureSpec.makeMeasureSpec(height,
                    heightMode == MeasureSpec.EXACTLY ? MeasureSpec.AT_MOST : heightMode);
            child.measure(childWidthMeasureSpec, childHeightMeasureSpec);

            if (line == null) {
                // 创建新一行
                line = new Line();
            }

            // 计算当前行已使用的宽度
            int measuredWidth = child.getMeasuredWidth();
            lineSize += measuredWidth;

            // 如果使用的宽度小于可用的宽度，这时候childView能够添加到当前的行上
            if (lineSize <= width) {
                line.addChild(child);
                lineSize += horizontalSpacing;
            } else {
                // 换行
                newLine();
                line.addChild(child);
                lineSize += child.getMeasuredWidth();
                lineSize += horizontalSpacing;
            }
        }

        // 把最后一行记录到集合中
        if (line != null && !lines.contains(line)) {
            lines.add(line);
        }

        int totalHeight = 0;
        // 把所有行的高度加上
        for (int i = 0; i < lines.size(); i++) {
            totalHeight += lines.get(i).getHeight();
        }
        // 加上行的竖直间距
        totalHeight += verticalSpacing * (lines.size() - 1);
        // 加上上下padding
        totalHeight += getPaddingBottom();
        totalHeight += getPaddingTop();

        // 设置自身尺寸
        // 设置布局的宽高，宽度直接采用父view传递过来的最大宽度，而不用考虑子view是否填满宽度
        // 因为该布局的特性就是填满一行后，再换行
        // 高度根据设置的模式来决定采用所有子View的高度之和还是采用父view传递过来的高度
        setMeasuredDimension(MeasureSpec.getSize(widthMeasureSpec),
                resolveSize(totalHeight, heightMeasureSpec));
    }

    private void restoreLine() {
        lines.clear();
        line = new Line();
        lineSize = 0;
    }

    private void newLine() {
        // 把之前的行记录下来
        if (line != null) {
            lines.add(line);
        }
        // 创建新的一行
        line = new Line();
        lineSize = 0;
    }

    @Override
    protected void onLayout(boolean changed, int l, int t, int r, int b) {
        super.onLayout(changed, l, t, r, b);
        int left = getPaddingLeft();
        int top = getPaddingTop();
        for (int i = 0; i < lines.size(); i++) {
            Line line = lines.get(i);
            line.layout(left, top);
            // 计算下一行的起点y轴坐标
            top = top + line.getHeight() + verticalSpacing;
        }
    }

    /**
     * 管理每行上的View对象
     */
    class Line {
        // 子控件集合
        private List<View> children = new ArrayList<View>();
        // 行高
        int height;

        /**
         * 添加childView
         *
         * @param childView 子控件
         */
        public void addChild(View childView) {
            children.add(childView);

            // 让当前的行高是最高的一个childView的高度
            if (height < childView.getMeasuredHeight()) {
                height = childView.getMeasuredHeight();
            }
        }

        /**
         * 指定childView的绘制区域
         *
         * @param left 左上角x轴坐标
         * @param top  左上角y轴坐标
         */
        public void layout(int left, int top) {
            int totalWidth = getMeasuredWidth() - getPaddingLeft() - getPaddingRight();
            // 当前childView的左上角x轴坐标
            int currentLeft = left;

            for (int i = 0; i < children.size(); i++) {
                View view = children.get(i);
                // 指定childView的绘制区域
                view.layout(currentLeft, top, currentLeft + view.getMeasuredWidth(),
                        top + view.getMeasuredHeight());
                // 计算下一个childView的位置
                currentLeft = currentLeft + view.getMeasuredWidth() + horizontalSpacing;
            }
        }

        public int getHeight() {
            return height;
        }

        public int getChildCount() {
            return children.size();
        }
    }

    public void checkDefault(String str) {
        if (isDataUpdated) {
            throw new RuntimeException("checkDefault must been invoked before update data.");
        }
        mDefaultCheckStr = str;
    }

    public void resetDefaultCheck() {
        mDefaultCheckStr = "";
        isDataUpdated = false;
    }

    /**
     * 增加关键字标签
     *
     * @param list 关键字
     */
    public void updateStr(List<String> list) {

        removeAllViews();

        for (String str: list) {
            setupFlowLayout(str);
        }

        isDataUpdated = true;
    }

    /**
     * 增加关键字标签
     *
     */
    public void update(List<T> dataList) {

        removeAllViews();
        mDataList.clear();
        mDataList.addAll(dataList);

        for (T entity : dataList) {
            setupFlowLayout(entity.getFlowName());
        }

        isDataUpdated = true;
    }

    private void setupFlowLayout(String text) {
        final RadioButton rb = new RadioButton(getContext());

        // 设置 RadioButton 属性
        rb.setText(text);
        rb.setTextSize(TypedValue.COMPLEX_UNIT_PX, textSize);
        rb.setTextColor(mContext.getResources().getColorStateList(textColorResource));
        rb.setGravity(Gravity.CENTER);
        rb.setPadding(textPaddingH, textPaddingV, textPaddingH, textPaddingV);
        rb.setButtonDrawable(null);

        rb.setClickable(true);
        rb.setBackgroundResource(backgroundResource);

        if (text.equals(mDefaultCheckStr)) {
            mCurrButton = rb;
            mCurrButton.setChecked(true);
            mPreButton = mCurrButton;
        }

        // 设置单选
        rb.setOnClickListener(new OnClickListener() {
            @Override
            public void onClick(View v) {
                mCurrButton = (RadioButton) v;

                if (mPreButton == null) {
                    mCurrButton.setChecked(true);
                    mPreButton = mCurrButton;
                }

                if (mCurrButton != mPreButton) {
                    mPreButton.setChecked(false);
                    mCurrButton.setChecked(true);
                    mPreButton = mCurrButton;
                }
            }
        });

        addView(rb, new ViewGroup.LayoutParams(ViewGroup.LayoutParams.WRAP_CONTENT,
                ViewGroup.LayoutParams.WRAP_CONTENT));

        if (mOnItemClickListener != null) {
            rb.setOnClickListener(new OnClickListener() {
                @Override
                public void onClick(View v) {
                    mOnItemClickListener.onItemClick(rb.getText().toString());
                }
            });
        }
    }

    /**
     * 点击事件监听
     */
    public interface OnItemClickListener {
        void onItemClick(String content);
    }

    /**
     * 设置文字水平间距
     *
     * @param horizontalSpacing 间距/dp
     */
    public void setHorizontalSpacing(int horizontalSpacing) {
        this.horizontalSpacing = dp2px(horizontalSpacing);
    }

    /**
     * 设置文字垂直间距
     *
     * @param verticalSpacing 间距/dp
     */
    public void serberticalSpacing(int verticalSpacing) {
        this.verticalSpacing = dp2px(verticalSpacing);
    }

    /**
     * 设置文字大小
     *
     * @param textSize 文字大小/sp
     */
    public void setTextSize(int textSize) {
        this.textSize = sp2px(textSize);
    }

    /**
     * 设置文字颜色
     *
     * @param textColorResource 文字颜色
     */
    public void setTextColorResourceId(int textColorResource) {
        this.textColorResource = textColorResource;
    }

    /**
     * 设置文字背景
     *
     * @param backgroundResource 文字背景
     */
    public void setBackgroundResource(int backgroundResource) {
        this.backgroundResource = backgroundResource;
    }

    /**
     * 设置文字水平padding
     *
     * @param textPaddingH padding/dp
     */
    public void setTextPaddingH(int textPaddingH) {
        this.textPaddingH = dp2px(textPaddingH);
    }

    /**
     * 设置文字垂直padding
     *
     * @param textPaddingV padding/dp
     */
    public void setTextPaddingV(int textPaddingV) {
        this.textPaddingV = dp2px(textPaddingV);
    }

    /**
     * dp转px
     *
     * @param dp dp值
     * @return px值
     */
    private int dp2px(float dp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_DIP, dp,
                getResources().getDisplayMetrics());
    }

    /**
     * sp转px
     *
     * @param sp sp值
     * @return px值
     */
    private int sp2px(float sp) {
        return (int) TypedValue.applyDimension(TypedValue.COMPLEX_UNIT_SP, sp,
                getResources().getDisplayMetrics());
    }

    public T getCheckedEntity() {

        if (ListUtil.isListEmpty(mDataList)) {
            return null;
        }

        for (int i = 0; i < getChildCount(); i++) {
            View childView = getChildAt(i);
            RadioButton rbChild = (RadioButton) childView;
            if (rbChild.isChecked()) {
                return mDataList.get(i);
            }
        }
        return null;
    }

    public String getCheckedString() {
        for (int i = 0; i < getChildCount(); i++) {
            View childView = getChildAt(i);
            RadioButton rbChild = (RadioButton) childView;
            if (rbChild.isChecked()) {
                return rbChild.getText().toString();
            }
        }
        return "";
    }

    /**
     * 传入的如果有实体信息，那么该实体要集成此类
     * 这样才可以通过 {@link FlowLayout#getCheckedEntity()} 获取到选中项以及对应的信息
     * <p>
     * 如果属性恰巧同名，请自行重载 getter & setter 方法进行覆盖
     */
    public static class FlowLayoutEntity {

        private String flowId;
        private String flowName;

        public String getFlowId() {
            return flowId;
        }

        public void setFlowId(String flowId) {
            this.flowId = flowId;
        }

        public String getFlowName() {
            return flowName;
        }

        public void setFlowName(String flowName) {
            this.flowName = flowName;
        }
    }

}